Skip to content

feat: Containers gear (Phase 1) — Docker monitoring + agent skipTLSVerify + buildx push-dev - #37

Merged
sarg3nt merged 8 commits into
mainfrom
feature/containers-gear
May 17, 2026
Merged

feat: Containers gear (Phase 1) — Docker monitoring + agent skipTLSVerify + buildx push-dev#37
sarg3nt merged 8 commits into
mainfrom
feature/containers-gear

Conversation

@sarg3nt

@sarg3nt sarg3nt commented May 10, 2026

Copy link
Copy Markdown
Owner

Summary

Resurrects the 2-month-old feature/containers-gear branch (last touched 2026-03-18), rebased onto current main. Bundles 4 themes:

  1. Containers gear (Phase 1) — new gear in both apps for Docker monitoring foundation: agent collector + detector + types, dashboard pages/JS/handlers/icons. ~1.4k lines.
  2. Agent skipTLSVerify option — new bool on NewClient / NewClientWithTimeout, with a DB migration adding skip_tls_verify to boxes, surfaced through HAProxy connection-test UI and box config.
  3. docker-push-dev Makefile target — buildx, multi-platform, pushes :dev directly to ghcr.io without going through GitHub Actions. Useful for fast feature-branch testing.
  4. RootHandler / gearPath — container navigation routing.

What I had to fix to land the rebase

  • gearbox/internal/framework/database/gears.go — main added GearHome const + HomeConfig struct in the same regions where this branch added GearContainers const + ContainersConfig struct. Kept both.
  • gearbox-agent/go.sum — main and the branch both bumped many indirect deps (modernc/sqlite migration etc.). Regenerated with go mod tidy.
  • gearbox/Makefile.PHONY line conflicted (main added deploy/deploy-build/deploy-restart, branch added docker-push-dev). Combined.
  • client_test.go / functional_test.go — these tests landed on main during the 2-month gap; they call NewClient with the old 2-arg signature. This branch's commit e275b19 added a 3rd skipTLSVerify arg. Updated all 39 call sites to pass false (the preserved default behavior). One commit on top of the rebase: 672ed34.

One commit (ef087f8 fix: update toggle function name in gearCard template) was dropped by git rebase as already-upstream — that fix landed via another path.

Test plan

  • CGO_ENABLED=0 go build ./... passes in both gearbox/ and gearbox-agent/
  • CGO_ENABLED=0 go test ./... passes in both modules
  • CI Lint passes (golangci-lint config sometimes drifts; flagging for visibility)
  • CI Build and Push completes for both linux/amd64 and linux/arm64
  • Manual smoke test of the new Containers gear in dev — collector connects, dashboard renders, settings save

Why Draft

Putting up as Draft because:

  • This is your in-progress work from March; you should be the one to drive it the rest of the way (further design choices, polish, integration with the post-rebrand "gears" platform).
  • Phase 2/3 of the Containers gear were presumably planned but not done.
  • The skipTLSVerify UX might benefit from a security review (InsecureSkipVerify is rarely the right default for new TLS clients).

🤖 Generated with Claude Code

sarg3nt and others added 7 commits May 10, 2026 01:20
Implements the initial Containers gear across both gearbox-agent and
gearbox dashboard, following the established gear architecture.

Agent (gearbox-agent):
- New gear at internal/gears/containers/ with Docker SDK (moby/moby/client)
- Runtime detection (gracefully degrades when Docker is absent)
- REST API: runtime info, container list, inspect, stats, logs, start/stop/restart/remove
- Stack (Compose project) detection and grouping via container labels
- Image listing endpoint
- 21 passing tests covering all endpoints and helper functions

Dashboard (gearbox):
- New gear at internal/gears/containers/ with plugin.go, handlers.go, icons.go
- Templ templates: containers page and settings
- Sidebar entry at /containers with container icon (order 50)
- Permission: containers:view / containers:manage
- GearContainers constant and ContainersConfig added to database/gears.go
- Default gear entry added (disabled by default)

Frontend:
- static/js/containers/containers-page.js — stacks view, all-containers
  view, search/filter, start/stop/restart actions, auto-refresh, confirm modal

Closes #24

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NewClient and NewClientWithTimeout grew a skipTLSVerify bool parameter
on this branch. The corresponding test files (client_test.go,
functional_test.go) landed on main during the 2-month gap and used the
old 2-arg signature, breaking the build after rebase. Pass false (the
preserved default) at all call sites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sarg3nt
sarg3nt marked this pull request as ready for review May 17, 2026 23:02
Copilot AI review requested due to automatic review settings May 17, 2026 23:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Resurrects a 2-month-old branch that introduces a Phase-1 Containers (Docker) gear in both the dashboard and the agent, adds a per-box skip_tls_verify option (replacing the global GEARBOX_INSECURE_TLS env var), and adds docker-push-dev Makefile targets. A new RootHandler redirects / to the first enabled gear.

Changes:

  • New containers gear (agent collector + types + dashboard page/templates/JS/icons) plus a SQL migration and BoxDB.SkipTLSVerify plumbed through every agent.NewClient call site and the HAProxy box UI/test flow.
  • docker-push-dev Makefile target in both modules.
  • RootHandler/gearPath for root-path navigation, with containers added to the gear path map.

Reviewed changes

Copilot reviewed 36 out of 37 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
gearbox/static/js/containers/containers-page.js New containers page JS; calls /api/v1/containers/* (no dashboard handlers exist).
gearbox/Makefile Adds docker-push-dev (linux/amd64 only).
gearbox/internal/gears/containers/settings.templ Stats interval settings UI with non-functional Save button.
gearbox/internal/gears/containers/plugin.go Dashboard gear registration; only registers the page route.
gearbox/internal/gears/containers/pages.templ Containers page layout.
gearbox/internal/gears/containers/icons.go Sidebar SVG icon.
gearbox/internal/gears/containers/handlers.go Containers page HTTP handler.
gearbox/internal/framework/templates/pages/haproxy_settings.templ Adds Skip TLS Verify checkbox to box form.
gearbox/internal/framework/templates/layouts/base.templ Adds containers to integration path map.
gearbox/internal/framework/models/server.go SkipTLSVerify on BoxConfig.
gearbox/internal/framework/handler/root.go New RootHandler and gearPath map.
gearbox/internal/framework/handler/haproxy_config.go Propagates SkipTLSVerify; switches test probe from GetInfo to GetMetrics.
gearbox/internal/framework/handler/{gears,config,api_traffic,api_services,api_certificates}.go Pass SkipTLSVerify to agent.NewClient.
gearbox/internal/framework/database/servers.go Adds skip_tls_verify column to all box queries and ToBoxConfig.
gearbox/internal/framework/database/migrations/files/000001_add_skip_tls_verify_to_boxes.{up,down}.sql New migration; down migration recreates table via CREATE TABLE … AS SELECT ….
gearbox/internal/framework/database/gears.go Adds GearContainers constant, ContainersConfig, and default gear row.
gearbox/internal/framework/config/config.go Removes GEARBOX_INSECURE_TLS env var.
gearbox/internal/framework/collector/{websocket_manager,registry}.go Pass SkipTLSVerify to agent client.
gearbox/internal/framework/agent/client.go NewClient(WithTimeout) gains skipTLSVerify arg; createTLSConfig is per-call.
gearbox/internal/framework/agent/{client,functional}_test.go Test call-site updates for the new signature.
gearbox/cmd/server/main.go Imports containers gear; registers RootHandler at /.
gearbox-agent/Makefile Adds docker-push-dev.
gearbox-agent/cmd/gearbox-agent/main.go Imports containers gear.
gearbox-agent/go.{mod,sum} Adds moby/moby client + OpenTelemetry indirect deps.
gearbox-agent/internal/gears/containers/{types,plugin,plugin_test,detector,collector}.go New agent-side Docker collector, runtime detector, HTTP handlers, and tests.
Comments suppressed due to low confidence (1)

gearbox/static/js/containers/containers-page.js:279

  • stackAction and containerAction simply show a "coming in Phase 3" / "coming soon" toast and never actually call the agent. The stack Up/Down/Restart buttons in buildStackCard and the logs button in buildContainerRow are wired up to these stubs, so the UI advertises functionality that is non-operational. Either disable/hide these buttons in Phase 1 or implement the dashboard→agent proxy so they work; shipping always-no-op buttons leads to a confusing user experience.

Comment on lines +45 to +47
func (p *Gear) RegisterRoutes(r chi.Router) {
r.Get("/", p.handlers.ContainersPage)
}
@@ -0,0 +1,4 @@
-- SQLite does not support DROP COLUMN in older versions; recreate table without skip_tls_verify
CREATE TABLE boxes_backup AS SELECT id, box_id, name, location, notes, agent_url, api_key_encrypted, enabled, auto_discovery, created_at, updated_at, created_by FROM boxes;
Comment on lines +113 to +152
card.innerHTML = `
<div class="flex items-center justify-between px-4 py-3 cursor-pointer hover:bg-gray-50 dark:hover:bg-slate-750"
onclick="toggleStackExpand('${escHtml(stack.name)}')">
<div class="flex items-center gap-3">
<svg class="w-4 h-4 text-gray-400 dark:text-gray-500 stack-expand-icon transition-transform"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
<span class="font-semibold text-gray-900 dark:text-white">${escHtml(stack.name)}</span>
<span class="text-xs px-2 py-0.5 rounded-full font-medium ${statusColor}">
${running}/${total} running
</span>
</div>
<div class="flex items-center gap-2">
<button onclick="event.stopPropagation(); stackAction('${escHtml(stack.name)}', 'up')"
class="px-2 py-1 text-xs bg-green-600 hover:bg-green-700 text-white rounded transition-colors">Up</button>
<button onclick="event.stopPropagation(); stackAction('${escHtml(stack.name)}', 'down')"
class="px-2 py-1 text-xs bg-red-600 hover:bg-red-700 text-white rounded transition-colors">Down</button>
<button onclick="event.stopPropagation(); stackAction('${escHtml(stack.name)}', 'restart')"
class="px-2 py-1 text-xs bg-blue-600 hover:bg-blue-700 text-white rounded transition-colors">Restart</button>
</div>
</div>
<div class="stack-body hidden border-t border-gray-100 dark:border-slate-700 overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="bg-gray-50 dark:bg-slate-700/50 text-left">
<th class="px-4 py-2 text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">Name</th>
<th class="px-4 py-2 text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">Image</th>
<th class="px-4 py-2 text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">Status</th>
<th class="px-4 py-2 text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">CPU</th>
<th class="px-4 py-2 text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">Memory</th>
<th class="px-4 py-2 text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">Ports</th>
<th class="px-4 py-2 text-xs font-medium text-gray-500 dark:text-gray-400 uppercase">Actions</th>
</tr>
</thead>
<tbody id="stack-tbody-${escHtml(stack.name)}"></tbody>
</table>
</div>`;
renderContainerRows('stack-tbody-' + stack.name, stack.containers, false);
return card;
Comment thread gearbox/Makefile
Comment on lines +100 to +107
@docker buildx build \
--platform linux/amd64 \
--build-arg VERSION=dev \
--build-arg COMMIT_SHA=$(COMMIT_SHA) \
--build-arg BUILD_DATE=$(BUILD_DATE) \
-t $(IMAGE):dev \
--push \
.
// Step 2: Test authenticated endpoint
_, err = client.GetInfo()
// Step 2: Test authenticated endpoint — verifies the API key is valid
_, err = client.GetMetrics()
Comment on lines +32 to +36
<div class="mt-6">
<button class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors text-sm">
Save Settings
</button>
</div>
Resolve conflicts in:
  - gearbox-agent/cmd/gearbox-agent/main.go — keep both `containers`
    and `docker` gear imports (separate gears).
  - gearbox-agent/go.mod + go.sum — union of dependency sets;
    regenerated go.sum via `go mod tidy`. Adds Microsoft/go-winio,
    UserExistsError/conpty, creack/pty, containerd, docker, etc. as
    indirect deps for the two new gears.
  - gearbox/cmd/server/main.go — comment merge, includes /containers.
  - gearbox/internal/framework/database/servers.go — boxes table now
    carries BOTH SkipTLSVerify (from this PR) and ConsoleEnabled
    (from main). All SELECT / INSERT / UPDATE / Scan call sites
    updated to handle both columns.
  - gearbox/internal/framework/handler/haproxy_config.go — Create
    and Update box handlers read both skip_tls_verify and
    console_enabled form fields.
  - gearbox/internal/framework/templates/pages/haproxy_settings.templ
    — keep both the Skip-TLS checkbox and the Rotate-Key block.
  - gearbox/internal/framework/database/migrations/files/ — renumber
    PR 37's `000001_add_skip_tls_verify_to_boxes` migration to
    `000004` so it doesn't collide with main's
    `000001_add_failed_attempt_window`.

Propagate the SkipTLSVerify flag through the call sites that grew
since this PR was last rebased:
  - agent.NewClient / NewClientWithTimeout / NewClientWithKID /
    BuildTLSConfig now all take the skipTLSVerify flag.
  - CapabilitiesCache.Get accepts skipTLSVerify and passes it through.
  - Rotator.clientForKey threads it from BoxDB.SkipTLSVerify.
  - Bx status check uses b.SkipTLSVerify.
  - Console WS proxy uses server.SkipTLSVerify for BuildTLSConfig.

All `go build`, `go vet`, and `go test -count=1 ./...` pass clean in
both gearbox/ and gearbox-agent/ modules.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sarg3nt
sarg3nt merged commit 5a290f0 into main May 17, 2026
26 checks passed
@sarg3nt
sarg3nt deleted the feature/containers-gear branch May 17, 2026 23:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants